/*
@Desc : 提供db redis memcache的访问实例
@Version : 1.0.0
@Time : 2019/6/27 16:51 
@Author : hammercui
@File : dao
@Company: Sdbean
*/
package dao

import (
	"context"
	"time"

	"github.com/bilibili/kratos/pkg/cache/memcache"
	"github.com/bilibili/kratos/pkg/cache/redis"
	"github.com/bilibili/kratos/pkg/conf/paladin"
	"github.com/bilibili/kratos/pkg/database/sql"
	"github.com/bilibili/kratos/pkg/log"
	xtime "github.com/bilibili/kratos/pkg/time"
)

// Dao dao.
type Dao struct {
	db          *sql.DB
	redis       *redis.Pool
	redisExpire int32
	//mc          *memcache.Memcache
	//mcExpire    int32
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

// New new a dao and return.
func New() (dao *Dao) {
	var (
		dc struct {
			Demo *sql.Config
		}
		rc struct {
			Demo       *redis.Config
			DemoExpire xtime.Duration
		}
		mc struct {
			Demo       *memcache.Config
			DemoExpire xtime.Duration
		}
	)
	checkErr(paladin.Get("mysql.toml").UnmarshalTOML(&dc))
	checkErr(paladin.Get("redis.toml").UnmarshalTOML(&rc))
	checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc))
	dao = &Dao{
		// mysql
		db: sql.NewMySQL(dc.Demo),
		// redis
		redis:       redis.NewPool(rc.Demo),
		redisExpire: int32(time.Duration(rc.DemoExpire) / time.Second),
		// memcache
		//mc:       memcache.New(mc.Demo),
		//mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second),
	}
	//检测连通性
	if err := dao.db.Ping(context.Background());err !=nil{
		log.Error("ping Mysql err:%v",err)
	}
	log.Info("ping Mysql success!")

	dao.pingRedis(context.Background())
	return
}

// Close close the resource.
func (d *Dao) Close() {
	//d.mc.Close()
	d.redis.Close()
	d.db.Close()
}

// Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) {
	//if err = d.pingMC(ctx); err != nil {
	//	return
	//}
	if err = d.pingRedis(ctx); err != nil {
		return
	}
	return d.db.Ping(ctx)
}

//func (d *Dao) pingMC(ctx context.Context) (err error) {
//	if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
//		log.Error("conn.Set(PING) error(%v)", err)
//	}
//	return
//}

func (d *Dao) pingRedis(ctx context.Context) (err error) {
	conn := d.redis.Get(ctx)
	defer conn.Close()
	if _, err = conn.Do("SET", "ping", "pong"); err != nil {
		log.Error("ping Redis error(%v)", err)
	}
	log.Info("ping Redis success!")
	return
}

//测试mysql连接
func (d *Dao) pingMysql(ctx context.Context) (err error){
	if err = d.db.Ping(ctx);err !=nil{
		log.Error("ping Mysql err:%v",err)
	}
	log.Info("ping Mysql success!")
	return
}
